Micron Document
🎖️GitЯра🎖️


Displaying Raw • Download

build-logic/convention/src/main/kotlin/org/meshtastic/buildlogic/ProjectExtensions.kt bd2863243bab6eb213401d949839a2bc74dde7e2 (bd286324) Text, 6.67 KB

T8b949e/*
* Copyright (c) 2026 Meshtastic LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
Tff7b72package T7ee787org.meshtastic.buildlogic

Tff7b72import T7ee787com.gradle.develocity.agent.gradle.test.DevelocityTestConfiguration
Tff7b72import T7ee787org.gradle.api.Project
Tff7b72import T7ee787org.gradle.api.artifacts.ExternalModuleDependencyBundle
Tff7b72import T7ee787org.gradle.api.artifacts.MinimalExternalModuleDependency
Tff7b72import T7ee787org.gradle.api.artifacts.VersionCatalog
Tff7b72import T7ee787org.gradle.api.artifacts.VersionCatalogsExtension
Tff7b72import T7ee787org.gradle.api.provider.Provider
Tff7b72import T7ee787org.gradle.api.tasks.testing.AbstractTestTask
Tff7b72import T7ee787org.gradle.api.tasks.testing.Test
Tff7b72import T7ee787org.gradle.api.tasks.testing.logging.TestLogEvent
Tff7b72import T7ee787org.gradle.kotlin.dsl.configure
Tff7b72import T7ee787org.gradle.kotlin.dsl.getByType
Tff7b72import T7ee787org.gradle.kotlin.dsl.withType
Tff7b72import T7ee787org.gradle.plugin.use.PluginDependency
Tff7b72import T7ee787java.io.FileInputStream
Tff7b72import T7ee787java.util.Properties

Tff7b72private Tff7b72const Tff7b72val Te6edf3MAX_TEST_RETRIES Tff7b72= T79c0ff2
Tff7b72private Tff7b72const Tff7b72val Te6edf3MAX_TEST_FAILURES Tff7b72= T79c0ff1T79c0ff0

Tff7b72val Te6edf3ProjectTb4b4b4.Te6edf3libs
Tff7b72getTb4b4b4(Tb4b4b4)Tb4b4b4: Te6edf3VersionCatalog Tff7b72= Te6edf3extensionsTb4b4b4.Te6edf3getByTypeTff7b72<Te6edf3VersionCatalogsExtensionTff7b72>Tb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3namedTb4b4b4(Ta5d6ff"Ta5d6fflibsTa5d6ff"Tb4b4b4)

Tff7b72fun Te6edf3VersionCatalogTb4b4b4.Td2a8fflibraryTb4b4b4(Te6edf3aliasTb4b4b4: Tffa657StringTb4b4b4)Tb4b4b4: Te6edf3ProviderTff7b72<Te6edf3MinimalExternalModuleDependencyTff7b72> Tff7b72= Te6edf3findLibraryTb4b4b4(Te6edf3aliasTb4b4b4)Tb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)

Tff7b72fun Te6edf3VersionCatalogTb4b4b4.Td2a8ffbundleTb4b4b4(Te6edf3aliasTb4b4b4: Tffa657StringTb4b4b4)Tb4b4b4: Te6edf3ProviderTff7b72<Te6edf3ExternalModuleDependencyBundleTff7b72> Tff7b72= Te6edf3findBundleTb4b4b4(Te6edf3aliasTb4b4b4)Tb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)

Tff7b72fun Te6edf3VersionCatalogTb4b4b4.Td2a8ffpluginTb4b4b4(Te6edf3aliasTb4b4b4: Tffa657StringTb4b4b4)Tb4b4b4: Te6edf3ProviderTff7b72<Te6edf3PluginDependencyTff7b72> Tff7b72= Te6edf3findPluginTb4b4b4(Te6edf3aliasTb4b4b4)Tb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)

Tff7b72fun Te6edf3VersionCatalogTb4b4b4.Td2a8ffversionTb4b4b4(Te6edf3aliasTb4b4b4: Tffa657StringTb4b4b4)Tb4b4b4: Tffa657String Tff7b72= Te6edf3findVersionTb4b4b4(Te6edf3aliasTb4b4b4)Tb4b4b4.Te6edf3getTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3requiredVersion

Tff7b72val Te6edf3ProjectTb4b4b4.Te6edf3configPropertiesTb4b4b4: Te6edf3Properties
Tff7b72getTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3key Tff7b72= Ta5d6ff"Ta5d6ffmeshtastic.configPropertiesTa5d6ff"
Tff7b72val Te6edf3ext Tff7b72= Te6edf3extensionsTb4b4b4.Te6edf3extraProperties
Tf0883e@SuppressTb4b4b4(Ta5d6ff"Ta5d6ffUNCHECKED_CASTTa5d6ff"Tb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3extTb4b4b4.Te6edf3hasTb4b4b4(Te6edf3keyTb4b4b4)Tb4b4b4) Tff7b72return Te6edf3extTb4b4b4.Te6edf3getTb4b4b4(Te6edf3keyTb4b4b4) Tff7b72as Te6edf3Properties
Tff7b72val Te6edf3properties Tff7b72= Te6edf3PropertiesTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3propertiesFile Tff7b72= Te6edf3isolatedTb4b4b4.Te6edf3rootProjectTb4b4b4.Te6edf3projectDirectoryTb4b4b4.Te6edf3fileTb4b4b4(Ta5d6ff"Ta5d6ffconfig.propertiesTa5d6ff"Tb4b4b4)Tb4b4b4.Te6edf3asFile
Tff7b72if Tb4b4b4(Te6edf3propertiesFileTb4b4b4.Te6edf3existsTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3FileInputStreamTb4b4b4(Te6edf3propertiesFileTb4b4b4)Tb4b4b4.Te6edf3use Tb4b4b4{ Te6edf3propertiesTb4b4b4.Te6edf3loadTb4b4b4(Tffa657itTb4b4b4) Tb4b4b4}
Tb4b4b4}
Te6edf3extTb4b4b4.Te6edf3setTb4b4b4(Te6edf3keyTb4b4b4, Te6edf3propertiesTb4b4b4)
Tff7b72return Te6edf3properties
Tb4b4b4}

T8b949e/** Configure common test options like parallel execution and logging. */
Tff7b72internal Tff7b72fun Te6edf3ProjectTb4b4b4.Td2a8ffconfigureTestOptionsTb4b4b4(Tb4b4b4) Tb4b4b4{
T8b949e// Gradle 9 requires junit-platform-launcher on every test runtime classpath when
T8b949e// useJUnitPlatform() is active. Add it lazily to all *UnitTestRuntimeClasspath and
T8b949e// *TestRuntimeClasspath configurations so all Android and JVM test tasks get it
T8b949e// without requiring per-module declarations.
Te6edf3configurations
Tb4b4b4.Te6edf3matching Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3nameTb4b4b4.Te6edf3endsWithTb4b4b4(Ta5d6ff"Ta5d6ffUnitTestRuntimeClasspathTa5d6ff"Tb4b4b4) Tff7b72|Tff7b72| Tffa657itTb4b4b4.Te6edf3nameTb4b4b4.Te6edf3endsWithTb4b4b4(Ta5d6ff"Ta5d6ffTestRuntimeClasspathTa5d6ff"Tb4b4b4) Tb4b4b4}
Tb4b4b4.Te6edf3configureEach Tb4b4b4{
Tff7b72val Te6edf3launcher Tff7b72= Te6edf3libsTb4b4b4.Te6edf3libraryTb4b4b4(Ta5d6ff"Ta5d6ffjunit-platform-launcherTa5d6ff"Tb4b4b4)
Te6edf3projectTb4b4b4.Te6edf3dependenciesTb4b4b4.Te6edf3addTb4b4b4(Te6edf3nameTb4b4b4, Te6edf3launcherTb4b4b4)
Tb4b4b4}

Te6edf3tasksTb4b4b4.Te6edf3withTypeTff7b72<Te6edf3TestTff7b72>Tb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3configureEach Tb4b4b4{
T8b949e// JUnit 5: activate JUnit Platform — but NOT for androidHostTest (Robolectric) tasks
T8b949e// in KMP modules. Those tasks run JUnit 4 natively; applying useJUnitPlatform()
T8b949e// would force kotlin-test-junit5 selection which conflicts with the kotlin-test-junit
T8b949e// that Kotlin auto-selects for Robolectric @RunWith tests when Platform is absent.
Tff7b72if Tb4b4b4(Te6edf3name Tff7b72!Tff7b72= Ta5d6ff"Ta5d6fftestAndroidHostTestTa5d6ff"Tb4b4b4) Tb4b4b4{
Te6edf3useJUnitPlatformTb4b4b4(Tb4b4b4)
Tb4b4b4}
T8b949e// Parallelize unit tests at the Gradle fork level.
T8b949e// In CI, use all available processors; locally use half to keep the machine responsive.
Tff7b72val Te6edf3isCi Tff7b72= Te6edf3projectTb4b4b4.Te6edf3findPropertyTb4b4b4(Ta5d6ff"Ta5d6ffciTa5d6ff"Tb4b4b4) Tff7b72=Tff7b72= Ta5d6ff"Ta5d6fftrueTa5d6ff"
Te6edf3maxParallelForks Tff7b72=
Tff7b72if Tb4b4b4(Te6edf3isCiTb4b4b4) Tb4b4b4{
Te6edf3RuntimeTb4b4b4.Te6edf3getRuntimeTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3availableProcessorsTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3coerceAtLeastTb4b4b4(T79c0ff1Tb4b4b4)
Tb4b4b4} Tff7b72else Tb4b4b4{
Tb4b4b4(Te6edf3RuntimeTb4b4b4.Te6edf3getRuntimeTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3availableProcessorsTb4b4b4(Tb4b4b4) Tff7b72/ T79c0ff2Tb4b4b4)Tb4b4b4.Te6edf3coerceAtLeastTb4b4b4(T79c0ff1Tb4b4b4)
Tb4b4b4}
Te6edf3maxHeapSize Tff7b72= Ta5d6ff"Ta5d6ff2gTa5d6ff"

T8b949e// Keep forked test JVMs headless: Robolectric/Compose tests otherwise initialize
T8b949e// AWT on macOS, spawning a Dock icon per fork and stealing window focus.
T8b949e// apple.awt.UIElement covers anything that flips headless back off.
Te6edf3systemPropertyTb4b4b4(Ta5d6ff"Ta5d6ffjava.awt.headlessTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6fftrueTa5d6ff"Tb4b4b4)
Te6edf3jvmArgsTb4b4b4(Ta5d6ff"Ta5d6ff-Dapple.awt.UIElement=trueTa5d6ff"Tb4b4b4)

T8b949e// JUnit Jupiter parallel execution within each Gradle fork.
T8b949e// Classes run sequentially ("same_thread") because 19+ ViewModel test classes use
T8b949e// Dispatchers.setMain() — a JVM-global singleton that races when classes execute
T8b949e// concurrently in the same JVM. Cross-module parallelism via Gradle forks (above)
T8b949e// already provides the primary test speedup.
Te6edf3systemPropertyTb4b4b4(Ta5d6ff"Ta5d6ffjunit.jupiter.execution.parallel.enabledTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6fftrueTa5d6ff"Tb4b4b4)
Te6edf3systemPropertyTb4b4b4(Ta5d6ff"Ta5d6ffjunit.jupiter.execution.parallel.mode.defaultTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffsame_threadTa5d6ff"Tb4b4b4)
Te6edf3systemPropertyTb4b4b4(Ta5d6ff"Ta5d6ffjunit.jupiter.execution.parallel.mode.classes.defaultTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffsame_threadTa5d6ff"Tb4b4b4)
Te6edf3systemPropertyTb4b4b4(Ta5d6ff"Ta5d6ffjunit.jupiter.execution.parallel.config.strategyTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffdynamicTa5d6ff"Tb4b4b4)
Te6edf3systemPropertyTb4b4b4(Ta5d6ff"Ta5d6ffjunit.jupiter.execution.parallel.config.dynamic.factorTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff1Ta5d6ff"Tb4b4b4)

T8b949e// Allow modules with no discovered tests to pass without failing the build
Te6edf3filter Tb4b4b4{ Te6edf3isFailOnNoMatchingTests Tff7b72= Tff7b72false Tb4b4b4}

T8b949e// Show test results in the console
Te6edf3testLogging Tb4b4b4{ Te6edf3eventsTb4b4b4(Te6edf3TestLogEventTb4b4b4.Te6edf3PASSEDTb4b4b4, Te6edf3TestLogEventTb4b4b4.Te6edf3SKIPPEDTb4b4b4, Te6edf3TestLogEventTb4b4b4.Te6edf3FAILEDTb4b4b4) Tb4b4b4}
Tb4b4b4}

T8b949e// Gradle 9+ fails when test sources exist but no test classes are discovered (e.g. all
T8b949e// tests are commented out). Disable to avoid breaking builds for modules with WIP tests.
Te6edf3tasksTb4b4b4.Te6edf3withTypeTff7b72<Te6edf3AbstractTestTaskTff7b72>Tb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3configureEach Tb4b4b4{ Te6edf3failOnNoDiscoveredTestsTb4b4b4.Te6edf3setTb4b4b4(Tff7b72falseTb4b4b4) Tb4b4b4}

T8b949e// Develocity-native test retry; findByType no-ops if the settings plugin isn't applied.
Te6edf3tasksTb4b4b4.Te6edf3withTypeTff7b72<Te6edf3TestTff7b72>Tb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3configureEach Tb4b4b4{
Te6edf3extensionsTb4b4b4.Te6edf3findByTypeTb4b4b4(Te6edf3DevelocityTestConfigurationTff7b72::Te6edf3classTb4b4b4.Te6edf3javaTb4b4b4)Tff7b72?.Te6edf3testRetry Tb4b4b4{
Te6edf3maxRetriesTb4b4b4.Te6edf3setTb4b4b4(Te6edf3MAX_TEST_RETRIESTb4b4b4)
Te6edf3maxFailuresTb4b4b4.Te6edf3setTb4b4b4(Te6edf3MAX_TEST_FAILURESTb4b4b4)
T8b949e// Retry still isolates an ordering flake to one worker, but the build must not report success:
T8b949e// a green tick over a recorded <failure> hid a real cross-test coroutine leak for weeks.
Te6edf3failOnPassedAfterRetryTb4b4b4.Te6edf3setTb4b4b4(Tff7b72trueTb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tb4b4b4}

Served by rngit 1.5.0 - Generated in 0.06s